/**
 * @Form.js
 * @author zhangxinxu
 * @version
 * @created  16-03-01
 * @edited   19-12-02
 * @edited   22-06-01
 */
/**
 * 表单解决方案组件
 * @使用示例
 *  <form is="ui-form">
**/

/**/import '../LightTip/index.js';
/**/import Validate from '../Validate/index.js';
/**/import '../Loading/index.js';
 
/**/;(async () => {
/**/    if (!CSS.supports('overflow-anchor:auto') || !CSS.supports('offset:none')) {
/**/        await import('../safari-polyfill.js');
/**/    }
    // 表单
    class Form extends HTMLFormElement {
        constructor () {
            super();

            this.element = this.element || {};
            this.params = this.params || {
                // 验证成功之后，请求发送前的条件约束
                // avoidSend: function () {}
            };
            // 回调方法们
            this.callback = this.callback || {};

            Object.defineProperty(this.params, 'validate', {
                set (value) {
                    if (this.validate) {
                        this.validate.setCustomValidity(value);
                    }
                }
            });

            return this;
        }

        /**
         * 表单提交的处理
         * @return {[type]} [description]
         */
        ajax () {
            // 回调
            // optionCallback可以是对象也可以直接是成功回调
            /*
                optionCallback = {
                    success: function () {},
                    error: function () {},
                    complete: function () {}
                };
            */
            let optionCallback = this.callback;
            optionCallback = optionCallback || function () {};
            if (typeof optionCallback == 'function') {
                optionCallback = {
                    success: optionCallback
                };
            }
            // 元素
            let eleButton = null;
            let eleSubmit = this.element.submit;

            // 我们肉眼所见的按钮，进行一些状态控制
            eleButton = eleSubmit.id && document.querySelector('label[for=' + eleSubmit.id + ']');
            if (!eleButton) {
                eleButton = eleSubmit;
            }
            this.element.button = eleButton;

            // 请求地址
            let strUrl = this.action.split('#')[0] || location.href.split('#')[0];
            // 请求类型
            let strMethod = this.method || 'POST';
            let strEnctype = this.enctype;

            // 提交数据
            // 1. 菊花转起来
            eleButton.loading = true;
            // 2. 提交按钮禁用
            eleSubmit.setAttribute('disabled', 'disabled');

            // 3. 数据
            let objFormData = new FormData(this);
            // 支持外部传入额外的请求参数
            if (this.params.data) {
                Object.keys(this.params.data).forEach(key => {
                    objFormData.append(key, this.params.data[key]);
                });
            }

            // 请求类型不同，数据地址也不一样
            let strSearchParams = new URLSearchParams(objFormData).toString();

            if (strMethod.toLowerCase() == 'get') {
                if (strUrl.split('?').length > 1) {
                    strUrl = strUrl + '&' + strSearchParams;
                } else {
                    strUrl = strUrl + '?' + strSearchParams;
                }
            }

            // 4. 请求走起来
            let xhr = new XMLHttpRequest();
            xhr.open(strMethod, strUrl);

            if (optionCallback.beforeSend) {
                optionCallback.beforeSend.call(this, xhr, objFormData);
            }

            // 请求结束
            xhr.onload = () => {
                let json = {};

                try {
                    json = JSON.parse(xhr.responseText);
                } catch (event) {
                    new LightTip('返回数据解析出错。', 'error');
                    // 回调
                    if (optionCallback.error) {
                        optionCallback.error.call(this, event);
                    }

                    // 触发出错自定义事件
                    this.dispatchEvent(new CustomEvent('error', {
                        detail: {
                            data: {
                                code: -1,
                                msg: '解析出错'
                            }
                        }
                    }));

                    return;
                }

                if (json && (json.code === 0 || json.error === 0)) {
                    // 成功回调
                    if (optionCallback.success) {
                        optionCallback.success.call(this, json);
                    } else {
                        // 如果没有成功回调，组件自己提示成功
                        new LightTip(json.msg || '操作成功。', 'success');
                        // 表单重置
                        this.reset();
                    }

                    // 支持绑定success事件
                    this.dispatchEvent(new CustomEvent('success', {
                        detail: {
                            data: json
                        }
                    }));
                } else {
                    new LightTip((json && json.msg) || '返回数据格式不符合要求。', 'error');

                    // 失败回调
                    if (optionCallback.error) {
                        optionCallback.error.call(this, json);
                    }

                    // 触发出错自定义事件
                    this.dispatchEvent(new CustomEvent('error', {
                        detail: {
                            data: json
                        }
                    }));
                }
            };

            // 请求错误
            xhr.onerror = () => {
                new LightTip('网络异常，刚才的操作没有成功，您可以稍后重试。', 'error');
                // 回调
                if (optionCallback.error) {
                    optionCallback.error.apply(this, arguments);
                }
                // 触发出错自定义事件
                this.dispatchEvent(new CustomEvent('error', {
                    detail: {
                        code: -1,
                        msg: '网络异常'
                    }
                }));
            };

            // 请求结束，无论成功还是失败
            xhr.onloadend = () => {
                // 菊花关闭
                eleButton.loading = false;
                // 表单恢复提交
                eleSubmit.removeAttribute('disabled');
                // 回调
                if (optionCallback.complete) {
                    optionCallback.complete.apply(this, arguments);
                }

                // 支持绑定complete事件
                this.dispatchEvent(new CustomEvent('complete'));
            };

            if (strEnctype && strEnctype.toLowerCase() === 'application/x-www-form-urlencoded') {
                xhr.send(strSearchParams);
            } else {
                xhr.send(objFormData);
            }
        }

        connectedCallback () {
            // 表单提交按钮元素的获取
            let eleSubmit = [...this.elements].filter(function (control) {
                return control.type && /^(?:submit|image)$/i.test(control.type);
            })[0] || this.querySelector('button:nth-last-of-type(1)');

            if (!eleSubmit) {
                eleSubmit = (() => {
                    let ele = document.createElement('button');
                    ele.type = 'submit';
                    ele.setAttribute('hidden', '');
                    this.appendChild(ele);

                    return ele;
                })();
            }

            this.element.submit = eleSubmit;

            // 绑定表单验证
            this.validate = new Validate(this, () => {
                let funAvoidSend = this.params.avoidSend || this.callback.avoidSend;
                // 验证成功之后
                if (!funAvoidSend || !funAvoidSend(this)) {
                    this.ajax();
                }
            }, this.params.validate || {});

            // 全局事件
            this.dispatchEvent(new CustomEvent('connected', {
                detail: {
                    type: 'ui-form'
                }
            }));

            this.isConnectedCallback = true;

            this.dispatchEvent(new CustomEvent('DOMContentLoaded'));
        }
    }

    if (!customElements.get('ui-form')) {
        customElements.define('ui-form', Form, {
            extends: 'form'
        });
    }
/**/})();
